package main

import (
	"bufio"
	"bytes"
	"encoding/binary"
	"fmt"
	"io"
	"log"
	"net"
)

func main() {
	l, err := net.Listen("tcp", ":8888")
	if err != nil {
		panic(err)
	}

	for {
		conn, err := l.Accept()
		if err != nil {
			log.Printf("accept err: %v", err)
			return
		}

		go handleConn(conn)
	}
}

func handleConn(conn net.Conn) {
	fmt.Println("new conn from:", conn.RemoteAddr())
	localBuf := new(bytes.Buffer)
	readBuf := make([]byte, 1024)
	for {
		n, err := conn.Read(readBuf)
		if err != nil {
			if err == io.EOF {
				fmt.Println("connection closed by client!")
				break
			}
		}

		localBuf.Write(readBuf[:n])

		scanner := bufio.NewScanner(localBuf)
		scanner.Split(SplitAt) // 自定义的 SplitFunc
		for scanner.Scan() {
			fmt.Println("data:", decode(scanner.Bytes()))
		}

		localBuf.Reset()
	}
}

type frame struct {
	packageLength int32
	headerLength  int16
	version       int32
	operation     string
	seqid         int32
	datad         string
}

func decode(data []byte) *frame {
	f := new(frame)
	binary.Read(bytes.NewReader(data[:4]), binary.BigEndian, &f.packageLength)
	binary.Read(bytes.NewReader(data[4:6]), binary.BigEndian, &f.headerLength)
	binary.Read(bytes.NewReader(data[6:8]), binary.BigEndian, &f.version)
	binary.Read(bytes.NewReader(data[8:12]), binary.BigEndian, &f.operation)
	binary.Read(bytes.NewReader(data[12:16]), binary.BigEndian, &f.seqid)
	datalen := int(f.packageLength) - int(f.headerLength)
	f.datad = string(data[16 : 16+datalen])
	return f
}

func SplitAt(data []byte, atEOF bool) (advance int, token []byte, err error) {
	dataLen := len(data)

	if atEOF && dataLen == 0 {
		return 0, nil, nil
	}

	if dataLen >= 16 {
		var packagelen int32
		binary.Read(bytes.NewReader(data[:4]), binary.BigEndian, &packagelen)
		if dataLen < int(packagelen) {
			return
		}
		return int(packagelen), data[0:int(packagelen)], nil
	}

	if atEOF {
		return dataLen, data, nil
	}

	return 0, nil, nil
}
